package leetcode.array;

/**
 * @author Cheng Jun
 * Description: 在一个 m*n 的棋盘的每一格都放有一个礼物，每个礼物都有一定的价值（价值大于 0）。
 * 你可以从棋盘的左上角开始拿格子里的礼物，并每次向右或者向下移动一格、直到到达棋盘的右下角。
 * 给定一个棋盘及其上面的礼物的价值，请计算你最多能拿到多少价值的礼物？
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @version 1.0
 * @date 2022/1/27 22:18
 */
public class maxValue {


    // [1,3,1],
    // [1,5,1],
    // [4,2,1]
    // 0 < grid.length <= 200
    // 0 < grid[0].length <= 200
    int max = 0;

    // 时间复杂度爆炸：O(2^(m+n-2)) 指数级时间复杂
    public int maxValue(int[][] grid) {
        dfs(grid, 0, 0, 0);
        return max;
    }

    void dfs(int[][] grid, int rowIndex, int colIndex, int value) {
        // 坐标越界
        if (rowIndex >= grid.length || colIndex > grid[0].length) {
            return;
        }
        value += grid[rowIndex][colIndex];
        this.max = Math.max(max, value);
        dfs(grid, rowIndex + 1, colIndex, value);
        dfs(grid, rowIndex, colIndex + 1, value);
    }

    // 01背包问题
    public int maxValue1(int[][] grid) {
        int row = grid.length;
        int col = grid[0].length;
        int[] max = new int[col];
        max[0] = grid[0][0];
        for (int j = 1; j < col; j++) {
            max[j] = max[j - 1] + grid[0][j];
        }
        for (int i = 1; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (j == 0 ) max[j] += grid[i][j];
                else max[j] = Math.max(max[j - 1], max[j]) + grid[i][j];
            }
        }
        return max[col - 1];
    }

}
